package com.simen.hellobytes;

import com.simen.hellobytes.exception.HexToByteException;

import java.io.IOException;

/**
 * Created by ABC on 2017/9/4.
 */
public class HexUtil {

    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * 将字节数组转为16进制字符串
     *
     * @param bytes
     * @return e.g. AABBCCDD
     */
    public static String bytesToHex(byte... bytes) {
        if (bytes == null || bytes.length == 0) {
            return "";
        }

        StringBuilder builder = new StringBuilder();
        bytesToHex(builder,bytes);
        return builder.toString();
    }

    public static void bytesToHex(Appendable appendable, byte... bytes) {
        if (bytes == null || bytes.length == 0) {
            return;
        }

        try {
            for (int index = 0; index < bytes.length; index++) {
                appendable.append(HEX_DIGITS[(bytes[index] >> 4) & 0x0f]);
                appendable.append(HEX_DIGITS[bytes[index] & 0x0f]);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String bytesToHex(byte[] bytes, int start, int length) {
        if (bytes == null || bytes.length == 0) {
            return "";
        }

        StringBuilder builder = new StringBuilder();
        for (int index = start, end = start + length; index < end; index++) {

            builder.append(HEX_DIGITS[(bytes[index] >> 4) & 0x0f]);
            builder.append(HEX_DIGITS[bytes[index] & 0x0f]);

        }

        return builder.toString();
    }

    /**
     * 将十六进制字符串转为字节
     *
     * @param stringH e.g. AABBCCDD
     * @return
     */
    public static byte[] hexToBytes(String stringH) {
        if (stringH == null || stringH.length() == 0) {
            return new byte[0];
        }
        byte[] srcData = stringH.getBytes();
        if (srcData.length % 2 != 0) {
            return new byte[0];
        }

        for (int i = 0; i < srcData.length; i++) {
            if (srcData[i] > 0x2f && srcData[i] < 0x3a) {  //[0,9]
                srcData[i] = (byte) (srcData[i] & 0x0f);
            } else if (srcData[i] > 0x40 && srcData[i] < 0x47) { //[A,F]
                srcData[i] = (byte) (srcData[i] - 0x37);
            } else if (srcData[i] > 0x60 && srcData[i] < 0x67) { //[a,f]
                srcData[i] = (byte) (srcData[i] - 0x57);
            } else {
                //非16进制字符
                throw new HexToByteException("found char " + srcData[i]);
            }
        }

        byte[] bytes = new byte[srcData.length / 2];
        for (int i = 0, j = 0; i < srcData.length; i += 2, j++) {
            bytes[j] = (byte) (srcData[i] << 4 | srcData[i + 1]);
        }

        return bytes;
    }

}
